package com.example.springboot.utils;

import cn.hutool.core.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.cglib.beans.BeanMap;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

@Slf4j
public class BeanCopyUtil {

    private BeanCopyUtil() {
    }

    public static void copyPropertiesIgnoreNull(Object src, Object target) {
        BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
    }

    private static String[] getNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<>();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) emptyNames.add(pd.getName());
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    public static <T> Map<String, String> beanToMap(T bean) {
        Map<String, String> map = new HashMap<>();
        if (Objects.isNull(bean)) {
            return map;
        }
        BeanMap beanMap = BeanMap.create(bean);
        for (Object key : beanMap.entrySet()) {
            if (Objects.isNull(beanMap.get(key))) {
                map.put(key + "", null);
            } else {
                map.put(key + "", beanMap.get(key) + "");
            }
        }
        return map;
    }

    public static <T> T mapToBean(Map<String, String> map, T bean) {
        if (map != null) {
            BeanMap beanMap = BeanMap.create(bean);
            beanMap.putAll(map);
        }
        return bean;
    }


    public static <T, S> T cast(S s, Class<T> tClass) {
        try {
            if (Objects.isNull(s)) {
                return null;
            }
            T t = tClass.newInstance();
            BeanUtil.copyProperties(s, t);
            return t;
        } catch (Exception e) {
           log.info("bean 复制异常 {}", e);
        }
        return null;
    }
}
